#include"curve.h"
// 初始化SDL相关环境
// 函数功能：初始化SDL相关环境，包括创建SDL窗口和渲染器
// 参数说明：
// - window：指向SDL_Window指针的指针，用于接收创建的窗口对象的地址，通过这个二级指针可以在函数外部获取到创建好的窗口指针。
// - renderer：指向SDL_Renderer指针的指针，用于接收创建的渲染器对象的地址，通过这个二级指针可以在函数外部获取到创建好的渲染器指针。
// 返回值：成功初始化并创建好窗口与渲染器则返回1，表示初始化成功；若初始化SDL过程中出现错误或者创建窗口、渲染器失败，则返回0，表示初始化失败。
int init_SDL(SDL_Window **window, SDL_Renderer **renderer) {
    // 初始化SDL的视频子系统，如果返回值小于0，表示初始化失败
    if (SDL_Init(SDL_INIT_VIDEO) < 0) {
        // 打印出SDL初始化失败的错误信息，SDL_GetError函数用于获取具体的错误描述字符串
        printf("SDL could not initialize! SDL_Error: %s\n", SDL_GetError());
        return 0;
    }

    // 使用SDL_CreateWindow函数创建一个窗口对象，传入窗口标题、初始位置（这里使用未定义位置，由系统决定）、窗口宽度（SCREEN_WIDTH）、窗口高度（SCREEN_HEIGHT）以及显示模式（这里是显示窗口）等参数
    // 将创建好的窗口对象的地址赋值给传入的window指针（通过解引用二级指针来操作），这样在函数外部就能通过这个指针访问该窗口了
    *window = SDL_CreateWindow("Function Plotting", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
                               SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
    // 判断窗口是否创建成功，如果窗口对象指针为NULL，说明创建失败
    if (*window == NULL) {
        // 打印出窗口创建失败的错误信息，方便排查问题
        printf("Window could not be created! SDL_Error: %s\n", SDL_GetError());
        return 0;
    }

    // 使用SDL_CreateRenderer函数基于已创建的窗口对象来创建一个渲染器对象，传入窗口指针、指定渲染驱动（-1表示使用默认的推荐驱动）以及渲染器的加速标志（这里使用加速渲染）等参数
    // 将创建好的渲染器对象的地址赋值给传入的renderer指针（同样通过解引用二级指针操作），使得在函数外部可以使用这个渲染器进行后续绘图等操作
    *renderer = SDL_CreateRenderer(*window, -1, SDL_RENDERER_ACCELERATED);
    // 判断渲染器是否创建成功，如果渲染器对象指针为NULL，则表示创建失败
    if (*renderer == NULL) {
        // 打印出渲染器创建失败的错误信息
        printf("Renderer could not be created! SDL_Error: %s\n", SDL_GetError());
        return 0;
    }

    return 1;
}
// 关闭SDL相关资源
void close_SDL(SDL_Window *window, SDL_Renderer *renderer) {
    SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(window);
    SDL_Quit();
}
// 绘制坐标轴（简单的x轴和y轴）
void draw_axes(SDL_Renderer *renderer) {
    // 绘制x轴
    SDL_SetRenderDrawColor(renderer, 255,0,0, 255);
    SDL_RenderDrawLine(renderer, 0, SCREEN_HEIGHT / 2, SCREEN_WIDTH, SCREEN_HEIGHT / 2);//使用sdl库函数绘制x,y轴
    // 绘制y轴
    SDL_RenderDrawLine(renderer, SCREEN_WIDTH / 2, 0, SCREEN_WIDTH / 2, SCREEN_HEIGHT);
}
// 绘制样本点
void draw_points(SDL_Renderer *renderer,DataPoint *points, int num_points) {
    SDL_SetRenderDrawColor(renderer, 255,0, 0, 255);  // 设置颜色为红色
	int i; 
    for (i = 0; i < num_points; i++) {
        int x = (int)(points[i].x * SCREEN_WIDTH / 10)+SCREEN_WIDTH/2;  // 根据坐标范围映射到窗口宽度
        int y = SCREEN_HEIGHT/2 -(int)(points[i].y * SCREEN_HEIGHT / 10);  // 注意坐标转换，y轴方向相反
        SDL_RenderDrawPoint(renderer, x, y);
    }
}
// 绘制一次函数曲线
void draw_linear_function(SDL_Renderer *renderer, double a1, double b1) {
    SDL_SetRenderDrawColor(renderer, 0, 255, 0, 255);  // 设置颜色为红色，示例颜色可改
    int x;
	for ( x = -SCREEN_WIDTH; x < SCREEN_WIDTH; x++) {
        double real_x = (double)x * 10 / SCREEN_WIDTH;  // 还原真实的 x 坐标范围
        double y = a1 * real_x + b1;
        int screen_y = SCREEN_HEIGHT/2 - (int)(y * SCREEN_HEIGHT / 10);  // 坐标转换
        SDL_RenderDrawPoint(renderer, x+SCREEN_WIDTH/2, screen_y);
    }
}
// 绘制二次函数曲线
void draw_quadratic_function(SDL_Renderer *renderer, double a2, double b2, double c2) {
    SDL_SetRenderDrawColor(renderer, 0, 50, 0, 255);  // 设置颜色为绿色，示例颜色可改
    int x;
	for (x = -SCREEN_WIDTH; x < SCREEN_WIDTH; x++) {
        double real_x = (double)x * 10/ SCREEN_WIDTH;// 还原真实的 x 坐标范围
        double y = a2 * real_x * real_x + b2 * real_x + c2;// 注意坐标转换，y轴方向相反
        int screen_y = SCREEN_HEIGHT/2 - (int)(y * SCREEN_HEIGHT / 10);
        SDL_RenderDrawPoint(renderer, x+SCREEN_WIDTH/2, screen_y);
    }
}
// 绘制三次函数曲线
void draw_cubic_function(SDL_Renderer *renderer, double a3, double b3, double c3, double d3) {
    SDL_SetRenderDrawColor(renderer, 0, 0, 50, 255);  // 设置颜色为蓝色，示例颜色可改
    int x;
	for (x = -SCREEN_WIDTH; x < SCREEN_WIDTH; x++) {
        double real_x = (double)x * 10/ SCREEN_WIDTH;// 还原真实的 x 坐标范围
        double y = a3 * real_x * real_x * real_x + b3 * real_x * real_x + c3 * real_x + d3;// 注意坐标转换，y轴方向相反
        int screen_y = SCREEN_HEIGHT/2- (int)(y * SCREEN_HEIGHT / 10);
        SDL_RenderDrawPoint(renderer, x+SCREEN_WIDTH/2, screen_y);
    }
}
